var el = document.querySelector('#wrapper');
        var animationFrameId = null;
        var currentValue;
        var itemHeight = 36;
        var visibleItemCount = 3;
        var valueIndex = 0;
        var rotateEffect = true;

        var VISIBEL_ITEMS_ANGLE_MAP = {
            3: -45,
            5: -20,
            7: -15
        };

        function getDragRange() {
            var valuesLength = 15;

            return [ -itemHeight * (valuesLength - Math.ceil(visibleItemCount / 2)), itemHeight * Math.floor(visibleItemCount / 2)];
        }

        function value2Translate(valueIndex) {
            var offset = Math.floor(visibleItemCount / 2);

            if (valueIndex !== -1) {
                return (valueIndex - offset) * -itemHeight;
            }
        }

        function translate2Value(translate) {
            translate = Math.round(translate / itemHeight) * itemHeight;
            var index = -(translate - Math.floor(visibleItemCount / 2) * itemHeight) / itemHeight;
            var items = el.querySelectorAll('.picker-item');

            console.log(index);
            [].forEach.call(items, function(item, index) {
                item.classList.remove('picker-selected');
            });

            items[index].classList.add('picker-selected');
        }

        function initEvents() {
            var dragState = {};
            var velocityTranslate, prevTranslate, pickerItems;

            draggable(el, {
                start: function(event) {
                    cancelAnimationFrame(animationFrameId);
                    animationFrameId = null;
                    dragState = {
                        range: getDragRange(),
                        start: new Date(),
                        startLeft: event.pageX,
                        startTop: event.pageY,
                        startTranslateTop: translateUtil.getElementTranslate(el).top
                    };
                    pickerItems = el.querySelectorAll('.picker-item');
                },

                drag: function(event) {
                    el.classList.add('dragging');

                    dragState.left = event.pageX;
                    dragState.top = event.pageY;

                    var deltaY = dragState.top - dragState.startTop;
                    var translate = dragState.startTranslateTop + deltaY;

                    translateUtil.translateElement(el, null, translate);
                    velocityTranslate = translate - prevTranslate || translate;

                    prevTranslate = translate;

                    if (rotateEffect) {
                        updateRotate(prevTranslate, pickerItems);
                    }
                }, 

                end: function() {
                    el.classList.remove('dragging');
                    var momentumRatio = 7;
                    var currentTranslate = translateUtil.getElementTranslate(el).top;
                    var duration = new Date() - dragState.start;

                    var momentumTranslate;
                    if (duration < 300) {
                        momentumTranslate = currentTranslate + velocityTranslate * momentumRatio;
                    }

                    console.log('momentumTranslate', momentumTranslate);

                    dragRange = dragState.range;

                    setTimeout(function() {
                        var translate;
                        if (momentumTranslate) {
                            translate = Math.round(momentumTranslate / itemHeight) * itemHeight;
                        } else {
                            translate = Math.round(currentTranslate / itemHeight) * itemHeight;
                        }

                        translate = Math.max(Math.min(translate, dragRange[1]), dragRange[0]);
                        translateUtil.translateElement(el, null, translate);

                        currentValue = translate2Value(translate);

                        if (rotateEffect) {
                            planUpdateRotate();
                        }
                    }, 10);

                    dragState = {};
                }
            });
        }

        function rotateElement(element, angle) {
            if (!element) return;
            var transformProperty = translateUtil.transformProperty;

            element.style[transformProperty] = element.style[transformProperty].replace(/rotateX\(.+?deg\)/gi, '') + `rotateX(${angle}deg)`;
        }

        function updateRotate(currentTranslate, pickerItems) {
            var dragRange = getDragRange();

            if (!pickerItems) {
                pickerItems = el.querySelectorAll('.picker-item');
            }

            if (currentTranslate === undefined) {
                currentTranslate = translateUtil.getElementTranslate(el).top;
            }

            var itemFit = Math.ceil(visibleItemCount / 2);
            var angleUnit = VISIBEL_ITEMS_ANGLE_MAP[visibleItemCount] || -20;

            [].forEach.call(pickerItems, function(item, index) {
                var itemOffsetTop = index * itemHeight;
                var translateOffset = dragRange[1] - currentTranslate;
                var itemOffset = itemOffsetTop - translateOffset;
                var percentage = itemOffset / itemHeight;

                var angle = angleUnit * percentage;
                if (angle > 180) angle = 180;
                if (angle < -180) angle = -180;

                rotateElement(item, angle);

                if (Math.abs(percentage) > itemFit) {
                    item.classList.add('picker-item-far');
                } else {
                    item.classList.remove('picker-item-far');
                }
            });
        }

        function planUpdateRotate() {
            cancelAnimationFrame(animationFrameId);

            animationFrameId = requestAnimationFrame(function() {
                updateRotate();
            });

            el.addEventListener(translateUtil.transitionProperty, function() {
                cancelAnimationFrame(animationFrameId);
                animationFrameId = null;
            });
        }

        function doOnValueChange() {
            translateUtil.translateElement(el, null, value2Translate(valueIndex));
        }

        function doOnValuesChange() {
            var items = el.querySelectorAll('.picker-item');
            [].forEach.call(items, function(item, index) {
                translateUtil.translateElement(item, null, itemHeight * index);
            });
            if (rotateEffect) {
                planUpdateRotate();
            }
        }

        function mounted() {
            initEvents();
            doOnValueChange();
            if (rotateEffect) {
                doOnValuesChange();
            }
        }

        document.addEventListener('DOMContentLoaded', mounted);